package com.hejia.bulbul.scheduler;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;

import com.hejia.alauda.entity.DayCount;
import com.hejia.alauda.service.PopularizeVisitHourStatsService;
import com.hejia.bulbul.service.UserOrderDayStatsService;

/**
 * 推广访问分时汇总统计作业
 * 
 * @author hyr
 *
 */
public class PopularizeVisitHourStatsScheduler {
	
	private static final Log logger = LogFactory.getLog(PopularizeVisitHourStatsScheduler.class);

	@Resource
	private PopularizeVisitHourStatsService popularizeVisitHourStatsService;
	
	@Resource
	private UserOrderDayStatsService userOrderDayStatsService;
	
	/**
	 * 统计当天数据
	 */
	// [秒] [分] [小时] [日] [月] [周] [年]
	@Scheduled(cron = "0 0/10 * * * ?")
	@Async("executor")
	public void statsTodayData() {
		logger.info("开始统计当天推广访问IP数");
		// 零点时统计前一天数据，避免漏算
		LocalDate date = null;
		if (new DateTime().getHourOfDay() == 0) {
			date = new LocalDate().minusDays(1);
		} else {
			date = new LocalDate();
		}
		this.popularizeVisitHourStatsService.statsVisitIPByDate(date);
		
		logger.info("结束统计当天推广访问IP数");
	}

	/**
	 * 统计所有推广IP访问分时数据
	 */
	//@Scheduled(fixedDelay =  100 * 365 * 24 * 60 * 60 * 1000)
	@Async("executor")
	public void statsAllData() {

		logger.info("开始统计所有推广访问IP数");
		try {
			List<LocalDate> dates = popularizeVisitHourStatsService.findVisitDates();
			for (LocalDate date : dates) {
				this.popularizeVisitHourStatsService.statsVisitIPByDate(date);
				Thread.sleep(500);
			}
			logger.info("结束统计所有推广访问IP数");
		} catch (Exception e) {
			logger.error("统计所有推广访问IP数失败", e);
		}
	}
	
	/**
	 * 统计当天用户订单数据
	 * 每10分钟执行一次
	 */
	@Scheduled(fixedDelay = 10 * 60 * 1000)
	@Async("executor")
	public void statsTodayUserOrderDayData() {
		logger.info("开始统计当天用户和订单");
		try {
			Date startDate = null;
			Date endDate = null;
			// 零点时统计前一天数据，避免漏算
			if (new DateTime().getHourOfDay() == 0) {
				startDate = new LocalDate().minusDays(1).toDate();
				endDate = new DateTime(startDate).plusDays(1).minusMillis(1).toDate();
			} else {
				startDate = new LocalDate().toDate();
				endDate = new Date();
			}
			statsUserOrderDayData(startDate, endDate, false);
		} catch (Exception e) {
			logger.error("统计当天用户和订单失败", e);
		}
		logger.info("结束统计当天用户和订单");
	}

	/**
	 * 按天统计所有用户和订单数据
	 */
	//@Scheduled(fixedDelay =  100 * 365 * 24 * 60 * 60 * 1000)
	@Async("executor")
	public void statsAllUserOrderDayData() {
		logger.info("开始按天统计所有用户和订单");
		try {
			Date startDate = DateFormatUtils.ISO_DATE_FORMAT.parse("2014-01-01");
			Date endDate = new Date();
			statsUserOrderDayData(startDate, endDate, true);
		} catch (Exception e) {
			logger.error("按天统计用户和订单失败", e);
		}
		logger.info("结束按天统计所有用户和订单");
	}
	
	/**
	 * 统计用户订单日数据
	 * @param startDate	开始日期
	 * @param endDate	结束日期
	 * @param sleep 是否停顿执行
	 * @throws Exception
	 */
	private void statsUserOrderDayData(Date startDate, Date endDate, boolean sleep) throws Exception {
		
		// 注册用户数
		List<DayCount> dayRegisteredUserCounts = this.userOrderDayStatsService.statsDayRegisteredUser(startDate, endDate);
		for (DayCount dayCount : dayRegisteredUserCounts) {
			this.userOrderDayStatsService.addOrUpdateDayRegisteredUserStats(dayCount);
			if (sleep) {
				Thread.sleep(500);
			}
		}
		
		// 新增交易用户数
		List<DayCount> dayNewTradeUserCounts = this.userOrderDayStatsService.statsDayNewTradeUserAndAmount(startDate, endDate);
		for (DayCount dayCount : dayNewTradeUserCounts) {
			this.userOrderDayStatsService.addOrUpdateDayNewTradeUserAndAmountStats(dayCount);
			if (sleep) {
				Thread.sleep(500);
			}
		}
		
		// 交易订单数
		List<DayCount> dayOrderCounts = this.userOrderDayStatsService.statsDayOrder(startDate, endDate);
		for (DayCount dayCount : dayOrderCounts) {
			this.userOrderDayStatsService.addOrUpdateDayOrderStats(dayCount);
			if (sleep) {
				Thread.sleep(500);
			}
		}
		
		// 成功交易订单数和金额
		List<DayCount> daySuccessOrderCounts = this.userOrderDayStatsService.statsDaySuccessOrderAndAmount(startDate, endDate);
		for (DayCount dayCount : daySuccessOrderCounts) {
			this.userOrderDayStatsService.addOrUpdateDaySuccessOrderAndAmountStats(dayCount);
			if (sleep) {
				Thread.sleep(500);
			}
		}
		
		// 复投订单数和金额
		List<DayCount> dayRepeatOrderCounts = this.userOrderDayStatsService.statsDayRepeatOrderAndAmount(startDate, endDate);
		for (DayCount dayCount : dayRepeatOrderCounts) {
			this.userOrderDayStatsService.addOrUpdateDayRepeatOrderAndAmountStats(dayCount);
			if (sleep) {
				Thread.sleep(500);
			}
		}
	}
}
